package com.demo.security.utils;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * String工具类
 *
 * @author OL
 */
public class NumberUtils {

	private NumberUtils() {}
	
	/**
	 * 判断是否为数字<br>
	 * 包括整数和小数
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isNumerical(Object obj) {
		if (obj == null) {
			return false;
		}
		return obj.toString().matches("-?\\d+(\\.\\d+)?");
	}

	/**
	 * 判断是否为Double
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isDouble(Object obj) {
		if (!isNumerical(obj)) {
			return false;
		}
		BigDecimal bigDecimal = new BigDecimal(obj.toString());
		if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Double.MAX_VALUE))) == 1) {
			return false;
		}
		if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Double.MIN_VALUE))) == -1) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否为Float
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isFloat(Object obj) {
		if (!isNumerical(obj)) {
			return false;
		}
		BigDecimal bigDecimal = new BigDecimal(obj.toString());
		if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Float.MAX_VALUE))) == 1) {
			return false;
		}
		if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Float.MIN_VALUE))) == -1) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否为长整数
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isLong(Object obj) {
		if (!isNumerical(obj)) {
			return false;
		}
		if (obj.toString().indexOf(".") >= 0) {
			return false;
		}
		BigInteger bigInteger = new BigInteger(obj.toString());
		if (bigInteger.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) == 1) {
			return false;
		}
		if (bigInteger.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) == -1) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否为整数
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isInteger(Object obj) {
		if (!isNumerical(obj)) {
			return false;
		}
		if (obj.toString().indexOf(".") >= 0) {
			return false;
		}
		BigInteger bigInteger = new BigInteger(obj.toString());
		if (bigInteger.compareTo(new BigInteger(String.valueOf(Integer.MAX_VALUE))) == 1) {
			return false;
		}
		if (bigInteger.compareTo(new BigInteger(String.valueOf(Integer.MIN_VALUE))) == -1) {
			return false;
		}
		return true;
	}
	
	/**
	 * 判断是否为短整数
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isShort(Object obj) {
		if (!isNumerical(obj)) {
			return false;
		}
		if (obj.toString().indexOf(".") >= 0) {
			return false;
		}
		BigInteger bigInteger = new BigInteger(obj.toString());
		if (bigInteger.compareTo(new BigInteger(String.valueOf(Short.MAX_VALUE))) == 1) {
			return false;
		}
		if (bigInteger.compareTo(new BigInteger(String.valueOf(Short.MIN_VALUE))) == -1) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否为小数
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isDecimal(Object obj) {
		if (!isNumerical(obj)) {
			return false;
		}
		return obj.toString().indexOf(".") >= 0;
	}

	/**
	 * 判断是否为小数
	 * 
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static boolean isDecimal(Object obj, int scale) {
		if (!isDecimal(obj)) {
			return false;
		}
		return obj.toString().matches("\\d+\\.\\d{" + scale + "}");
	}
	
	/**
	 * 将对象转换成Short<br>
	 * 转换失败将返回null
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Short toShort(Object obj) {
		return toShort(obj, null);
	}
	
	/**
	 * 将对象转换成Short<br>
	 * 转换失败将返回defaultValue
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Short toShort(Object obj, Short defaultValue) {
		if(isNumerical(obj)){
			BigDecimal bigDecimal = new BigDecimal(obj.toString());
			if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Short.MAX_VALUE))) == 1) {
				return defaultValue;
			}
			if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Short.MIN_VALUE))) == -1) {
				return defaultValue;
			}
			return bigDecimal.shortValue();
		}
		return defaultValue;
	}
	
	/**
	 * 将对象转换成Integer<br>
	 * 转换失败将返回null
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Integer toInteger(Object obj) {
		return toInteger(obj, null);
	}
	
	/**
	 * 将对象转换成Integer<br>
	 * 转换失败将返回defaultValue
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Integer toInteger(Object obj, Integer defaultValue) {
		if(isNumerical(obj)){
			BigDecimal bigDecimal = new BigDecimal(obj.toString());
			if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Integer.MAX_VALUE))) == 1) {
				return defaultValue;
			}
			if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Integer.MIN_VALUE))) == -1) {
				return defaultValue;
			}
			return bigDecimal.intValue();
		}
		return defaultValue;
	}
	
	/**
	 * 将对象转换成Long<br>
	 * 转换失败将返回null
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Long toLong(Object obj) {
		return toLong(obj, null);
	}
	
	/**
	 * 将对象转换成Long<br>
	 * 转换失败将返回defaultValue
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Long toLong(Object obj, Long defaultValue) {
		if(isNumerical(obj)){
			BigDecimal bigDecimal = new BigDecimal(obj.toString());
			if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Long.MAX_VALUE))) == 1) {
				return defaultValue;
			}
			if (bigDecimal.compareTo(new BigDecimal(String.valueOf(Long.MIN_VALUE))) == -1) {
				return defaultValue;
			}
			return bigDecimal.longValue();
		}
		return defaultValue;
	}
	
	/**
	 * 将对象转换成Float<br>
	 * 转换失败将返回null
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Float toFloat(Object obj) {
		return toFloat(obj, null);
	}
	
	/**
	 * 将对象转换成Float<br>
	 * 转换失败将返回defaultValue
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Float toFloat(Object obj, Float defaultValue) {
		if(isNumerical(obj)){
			BigDecimal bigDecimal = new BigDecimal(obj.toString());
			return bigDecimal.floatValue();
		}
		return defaultValue;
	}
	
	/**
	 * 将对象转换成Double<br>
	 * 转换失败将返回null
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Double toDouble(Object obj) {
		return toDouble(obj, null);
	}
	
	/**
	 * 将对象转换成Double<br>
	 * 转换失败将返回defaultValue
	 * @param obj
	 * @return
	 * @author OL
	 */
	public static Double toDouble(Object obj, Double defaultValue) {
		if(isNumerical(obj)){
			BigDecimal bigDecimal = new BigDecimal(obj.toString());
			return bigDecimal.doubleValue();
		}
		return defaultValue;
	}

	/**
	 * 格式化小数位数
	 * @param scala
	 * @param number
	 * @return
	 * @author OL
	 */
	public static String format(Double number, int scala){
		if(number == null){
			return null;
		}
        return String.format("%." + scala + "f", number);
	}
	
	/**
	 * 比较两个对象（不能有null值）<br>
	 * 当 o1 > o2 则返回值 > 0<br>
	 * 当 o1 = o2 则返回值 = 0<br>
	 * 当 o1 < o2 则返回值 < 0<br>
	 * @param o1
	 * @param o2
	 * @return
	 * @author OL
	 */
	public static int compare(Object o1, Object o2){
		return o1.toString().compareTo(o2.toString());
	}
	
	/**
	 * 取最小值
	 * @param n1
	 * @param n2
	 * @return
	 * @author OL
	 */
	@SuppressWarnings("unchecked")
	public static <T> T min(T... numbers){
		T min = null;
		if(numbers.length > 0){
			min = numbers[0];
			for (T n : numbers) {
				if(compare(n, min) < 0){
					min = n;
				}
			}
		}
		return min;
	}
	
	/**
	 * 取最小值
	 * @param n1
	 * @param n2
	 * @return
	 * @author OL
	 */
	@SuppressWarnings("unchecked")
	public static <T> T max(T... numbers){
		T max = null;
		if(numbers.length > 0){
			max = numbers[0];
			for (T n : numbers) {
				if(compare(n, max) > 0){
					max = n;
				}
			}
		}
		return max;
	}
	
	public static void main(String[] args) {
		// System.out.println(Long.MAX_VALUE);
		// System.out.println(Integer.MAX_VALUE);
		// System.out.println(Double.MAX_VALUE);
		// System.out.println(Float.MAX_VALUE);
		// System.out.println(isNumerical("1.0"));
		// System.out.println(isInteger("2147483647"));
		// System.out.println(isFloat("123556465"));
		// System.out.println(isDecimal("1235.56465"));
		// System.out.println(isDecimal("1235.56", 2));
		// System.out.println(isDecimal("1235.565", 2));
		
		/*System.out.println(compare(3, 3));
		System.out.println(compare(3, 2));
		System.out.println(compare(5, 2));
		System.out.println(compare("3", "2"));
		System.out.println(compare("aa", "ab"));
		System.out.println(compare("ac", "ab"));
		System.out.println(compare("aa", "ba"));
		System.out.println(compare("aa", "ca"));
		System.out.println(compare("aa", "cc"));
		System.out.println(compare("fa", "ca"));
		System.out.println(compare("f", "ca"));*/
		
		System.out.println(isNumerical(0));
		System.out.println(isNumerical(1));
		System.out.println(isNumerical(1.1));
		System.out.println(isNumerical(-1));
		System.out.println(isNumerical(-1.1));
		
		System.out.println(min(1, 2, 4, 2, 7, 0, -4));
		
		toLong(-5L, 0L);
		toDouble(-0.5, 0D);
	}
}
